home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / nn.zip / ARTICLES.C < prev    next >
C/C++ Source or Header  |  1989-12-29  |  9KB  |  413 lines

  1. /*
  2.  * access - get access to master data
  3.  */
  4.  
  5. #include "config.h"
  6. #include "db.h"
  7. #include "articles.h"
  8. #include "match.h"
  9.  
  10.  
  11. /*
  12.  * memory management
  13.  */
  14.  
  15. static thunk 
  16.     dummy_str_t = {
  17.     NULL,
  18.     NULL,
  19.     0L
  20.     }, 
  21.     dummy_art_t = {
  22.     NULL,
  23.     NULL,
  24.     0L
  25.     };
  26.  
  27.  
  28. static thunk *first_str_t = &dummy_str_t;
  29. static thunk *current_str_t = &dummy_str_t;
  30. static thunk *first_art_t = &dummy_art_t;
  31. static thunk *current_art_t = &dummy_art_t;
  32. static long  cur_str_size = 0, cur_art_size = 0;
  33. static char *next_str;
  34. static article_header *next_art, **art_array;
  35.  
  36. static article_number max_articles = 0, mem_offset = 0;
  37.  
  38. /*
  39.  * allocate one article header
  40.  */
  41.  
  42. #ifndef ART_THUNK_SIZE
  43. #define ART_THUNK_SIZE    127
  44. #endif
  45.  
  46. static new_thunk(t, ptr, size, chk_msg)
  47. thunk *t;
  48. char *ptr;
  49. long size;
  50. char *chk_msg;
  51. {
  52.     thunk *new;
  53.  
  54.     mem_check(ptr, (int)size, chk_msg);
  55.     
  56.     new = (thunk *)calloc(1, sizeof(thunk));
  57.     mem_check((char *)new, sizeof(thunk), "memory thunk");
  58.     
  59.     new->next_thunk = t->next_thunk;
  60.     t->next_thunk = new;
  61.     
  62.     new->this_thunk = ptr;
  63.     new->thunk_size = size;
  64. }
  65.  
  66.  
  67. article_header *alloc_art()
  68. {
  69.     if (cur_art_size == 0) {
  70.     if (current_art_t->next_thunk == NULL)
  71.         new_thunk(current_art_t,
  72.               calloc(ART_THUNK_SIZE, sizeof(article_header)),
  73.               (long)ART_THUNK_SIZE,
  74.               "article headers");
  75.  
  76.     current_art_t = current_art_t->next_thunk;
  77.     next_art = (article_header *)current_art_t->this_thunk;
  78.     cur_art_size = current_art_t->thunk_size;
  79.     }
  80.  
  81.     cur_art_size--;
  82.     return next_art++;
  83. }
  84.  
  85. /*
  86.  * allocate a string of length 'len'
  87.  */
  88.  
  89. #ifndef STR_THUNK_SIZE
  90. #define STR_THUNK_SIZE    ((1<<14) - 32)    /* leave room for malloc header */
  91. #endif
  92.  
  93. char *alloc_str(len)
  94. int len;
  95. {
  96.     char *ret;
  97.     
  98.     if (cur_str_size <= len) {    /* must be room for len+1 bytes */
  99.     if (current_str_t->next_thunk == NULL)
  100.         new_thunk(current_str_t, 
  101.               malloc(STR_THUNK_SIZE),
  102.               (long)STR_THUNK_SIZE,
  103.               "string bytes");
  104.  
  105.     current_str_t = current_str_t->next_thunk;
  106.     next_str = current_str_t->this_thunk;
  107.     cur_str_size = current_str_t->thunk_size;
  108.     }
  109.  
  110.     ret = next_str;
  111.     cur_str_size -= len + 1;
  112.     next_str += len;
  113.     *next_str++ = NUL;    /* string is null terminated */
  114.     
  115.     return ret;
  116. }    
  117.  
  118. /*
  119.  * "free" the allocated memory
  120.  */
  121.  
  122. free_memory()
  123. {
  124.     current_str_t = first_str_t;
  125.     current_art_t = first_art_t;
  126.     cur_str_size  = 0;
  127.     cur_art_size  = 0;
  128.     n_articles      = 0;
  129. }    
  130.  
  131.  
  132. /*
  133.  * mark/release memory
  134.  */
  135.  
  136.  
  137. mark_str(str_marker)
  138. string_marker *str_marker;
  139. {
  140.     str_marker->sm_cur_t = current_str_t;
  141.     str_marker->sm_size  = cur_str_size;
  142.     str_marker->sm_next  = next_str;
  143. }
  144.  
  145. release_str(str_marker)
  146. string_marker *str_marker;
  147. {
  148.     current_str_t = str_marker->sm_cur_t;
  149.     cur_str_size  = str_marker->sm_size;
  150.     next_str      = str_marker->sm_next;
  151. }
  152.  
  153.  
  154. mark_memory(mem_marker)
  155. memory_marker *mem_marker;
  156. {
  157.     mark_str(&(mem_marker->mm_string));
  158.     
  159.     mem_marker->mm_cur_t = current_art_t;
  160.     mem_marker->mm_size  = cur_art_size;
  161.     mem_marker->mm_next  = next_art;
  162.     
  163.     mem_marker->mm_nart     = n_articles;
  164.     mem_offset += n_articles;
  165.  
  166.     n_articles = 0;
  167.     articles = art_array + mem_offset;
  168. }
  169.  
  170. release_memory(mem_marker)
  171. memory_marker *mem_marker;
  172. {
  173.     release_str(&(mem_marker->mm_string));
  174.     
  175.     current_art_t = mem_marker->mm_cur_t;
  176.     cur_art_size  = mem_marker->mm_size;
  177.     next_art      = mem_marker->mm_next;
  178.     
  179.     n_articles = mem_marker->mm_nart;
  180.  
  181.     mem_offset -= n_articles;
  182.     articles = art_array + mem_offset;
  183. }
  184.  
  185. /*
  186.  * merge all memory chunks into one.
  187.  */
  188.  
  189. merge_memory()
  190. {
  191.     n_articles += mem_offset;
  192.     mem_offset = 0;
  193.     articles = art_array;
  194. }
  195.  
  196.  
  197. /*
  198.  * save article header in 'articles' array
  199.  * 'articles' is enlarged if too small
  200.  */
  201.  
  202. #define    FIRST_ART_ARRAY_SIZE    500    /* malloc header */
  203. #define    NEXT_ART_ARRAY_SIZE    512
  204.  
  205. add_article(art)
  206. article_header *art;
  207. {
  208.     register long n;
  209.     
  210.     if ((n_articles + mem_offset) == max_articles) {
  211.     /* must increase size of 'articles' */
  212.  
  213.     if (max_articles == 0) {
  214.         /* allocate initial 'articles' array */
  215.         max_articles = FIRST_ART_ARRAY_SIZE;
  216.         n = 0;
  217.     } else {
  218.         new_thunk(current_str_t, 
  219.               (char *)art_array, 
  220.               (long)(max_articles*sizeof(article_header **)),
  221.               "");
  222.         n = max_articles;
  223.         articles = art_array + n;
  224.         
  225.         max_articles += NEXT_ART_ARRAY_SIZE;
  226.     }
  227.     art_array = (article_header **)
  228.         calloc((unsigned)max_articles, sizeof(article_header **));
  229.     mem_check((char *)art_array, (int)max_articles, "article headers");
  230.     while (--n >= 0) art_array[n] = *--articles;
  231.     articles = art_array + mem_offset;
  232.     }
  233.     
  234.     articles[n_articles] = art;
  235.     n_articles++;
  236. }
  237.  
  238.  
  239. static char match_subject[128] = {
  240.     
  241. /*  NUL SOH STX ETX EOT ENQ ACK BEL BS  TAB NL  VT  FF  CR  SO  SI  */
  242.     00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 
  243.  
  244. /*  DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM  SUB ESC FS  GS  RS  US  */
  245.     00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 
  246.  
  247. /*  SP  !   "   #   $   %   &   '   (   )   *   +   ,   -   .   /   */
  248.     00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 99, 00, 00, 00, 00, 
  249. /*                                              ^^                  */
  250.  
  251. /*  0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?   */
  252.      1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 00, 00, 00, 00, 00, 00, 
  253.  
  254. /*  @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   */
  255.     00, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
  256.  
  257. /*  P   Q   R   S   T   U   V   W   X   Y   Z   [   \   ]   ^   _   */
  258.     26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 00, 00, 
  259.  
  260. /*  `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o   */
  261.     00, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
  262.  
  263. /*  p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~   DEL */
  264.     26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 00, 00
  265.  
  266. };
  267.  
  268.  
  269. static article_comp(ah1, ah2)
  270. article_header **ah1, **ah2;
  271. {
  272.     register char *a = (**ah1).subject, *b = (**ah2).subject;
  273.     register p;
  274.     
  275.     for (;; a++, b++) {
  276.     while (*a && MATCH_DROP(match_subject, *a)) a++;
  277.     while (*b && MATCH_DROP(match_subject, *b)) b++; 
  278.     if (*a == NUL) {
  279.         if (*b) return -1;
  280.         break;
  281.     }
  282.     if (*b == NUL) return 1;
  283.     if (p = MATCH_CMP(match_subject, *a, *b)) return p;
  284.     }
  285. /*    
  286.     if (p = (**ah1).replies - (**ah2).replies) return p;
  287.  */
  288.     if ((**ah1).t_stamp > (**ah2).t_stamp) return 1;
  289.     if ((**ah1).t_stamp == (**ah2).t_stamp) return 0;
  290.     return -1;
  291. }
  292.  
  293.  
  294. static article_equal(ah1, ah2)        /* ah1.hdr == ah2.hdr */
  295. article_header **ah1, **ah2;
  296. {
  297.     register char *a = (**ah1).subject, *b = (**ah2).subject;
  298.     
  299.     for (;; a++, b++) {
  300.     while (*a && MATCH_DROP(match_subject, *a)) a++;
  301.     while (*b && MATCH_DROP(match_subject, *b)) b++; 
  302.     if (*a == NUL) {
  303.         if (*b == NUL) break;
  304.         goto not_equal;
  305.     }
  306.     if (*b == NUL) goto not_equal;
  307.     if (MATCH_EQ(match_subject, *a, *b)) continue;
  308.     goto not_equal;
  309.     }
  310.     
  311.     return 1;
  312.     
  313.  not_equal:
  314.     return 0;
  315. }
  316.  
  317.  
  318. sort_articles()
  319. {
  320.     register article_header **app;
  321.     register long n;
  322.     
  323.     if (n_articles <= 1) return;
  324.  
  325.     qsort((char *)articles, (int)n_articles, sizeof(article_header *), article_comp);
  326.     
  327.     for (n = n_articles - 1, app = articles + 1; --n >= 0; app++)
  328.     if (article_equal(app, app - 1)) (**app).flag |= A_SAME;
  329. }
  330.  
  331.     
  332. static offset_cmp(a, b)
  333. article_header **a, **b;
  334. {
  335.     register long i;
  336.     
  337.     if ((i = (int)((*a)->a_number - (*b)->a_number)) == 0)
  338.     i = (*a)->fpos - (*b)->fpos;
  339.  
  340.     return (i > 0) ? 1 : (i < 0) ? -1 : 0;
  341. }
  342.  
  343. static age_cmp(ah1, ah2)
  344. article_header **ah1, **ah2;
  345. {
  346.     if ((**ah1).t_stamp > (**ah2).t_stamp) return 1;
  347.     if ((**ah1).t_stamp == (**ah2).t_stamp) return 0;
  348.     return -1;
  349. }
  350.  
  351.  
  352. unsort_articles(arrival)
  353. {
  354.     register article_number i;
  355.     
  356.     for (i = n_articles; --i >= 0;)
  357.     articles[i]->flag &= ~A_SAME;
  358.     
  359.     if (n_articles <= 1) return;
  360.     qsort((char *)articles, (int)n_articles, sizeof(article_header *), 
  361.       arrival ? offset_cmp : age_cmp);
  362. }
  363.  
  364. /*
  365.  * Eliminate articles with the A_KILL flag set preserving the present ordering.
  366.  * This will only release the last entries in the articles array.
  367.  * Neither strings nor articles headers are released.
  368.  */
  369.  
  370. elim_articles(list, list_lgt)
  371. register article_number *list;
  372. int list_lgt;
  373. {
  374.     register article_header **srca, **desta;
  375.     register article_number n, count;
  376.     int changed, llen;
  377.     
  378.     count = 0;
  379.     changed = 0, llen = 0;
  380.     for (n = 0, srca = desta = articles; n < n_articles; n++, srca++) {
  381.     if ((*srca)->flag & A_KILL) {
  382.         if (list_lgt > 0) {
  383.         if (n < *list) {
  384.             if (llen) changed = 1;
  385.         } else
  386.         if (n == *list) {
  387.             if (llen) {
  388.             llen++;
  389.             list_lgt--;
  390.             *list++ = -1;
  391.             } else
  392.             ++(*list);
  393.             changed = 1;
  394.         }
  395.         }
  396.         continue;
  397.     }
  398.     if (list_lgt > 0 && n == *list) {
  399.         *list++ = count;
  400.         list_lgt--;
  401.         llen++;
  402.     }
  403.     count++;
  404.     *desta++ = *srca;
  405.     }
  406.     if (list_lgt > 0) {
  407.     if (!llen) *list = 0;
  408.     changed = 1;
  409.     }
  410.     n_articles = count;
  411.     return changed;
  412. }
  413.